package com.foreveross.bsl.push.repository.custom.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.core.query.Update;

import com.foreveross.bsl.push.domain.entity.DeviceCheckin;
import com.foreveross.bsl.push.repository.custom.DeviceCheckinRepositoryCustom;
import com.google.common.collect.Maps;
import com.mongodb.WriteResult;

public class DeviceCheckinRepositoryImpl implements DeviceCheckinRepositoryCustom {

	@Autowired
	private MongoTemplate mongoTemplate;
	
	/* (non-Javadoc)
	 * @see com.foreveross.bsl.push.repository.custom.DeviceCheckinRepositoryCustom#findByTag(java.lang.String, java.lang.String)
	 */
	@Override
	public List<DeviceCheckin> findByTag(String tagKey, String tagValue, String appId) {
		Map<String, String> tags=Maps.newHashMap();
		tags.put(tagKey, tagValue);
		return findByTags(tags, appId);
	}

	/* (non-Javadoc)
	 * @see com.foreveross.bsl.push.repository.custom.DeviceCheckinRepositoryCustom#findByTags(java.util.Map)
	 */
	@Override
	public List<DeviceCheckin> findByTags(Map<String, String> tags, String appId) {
		Query query=this.buildQuery(tags, appId);
		query.skip(0).limit(1000);
		return mongoTemplate.find(query, DeviceCheckin.class);
	}
	
	/* (non-Javadoc)
	 * @see com.foreveross.bsl.push.repository.custom.DeviceCheckinRepositoryCustom#findByTags(java.util.Map, int, int)
	 */
	@Override
	public Page<DeviceCheckin> findByTags(Map<String, String> tags, String appId, Pageable pageable) {
		Query query=this.buildQuery(tags, appId);
		//TODO 待优化分页性能
		long cnt=this.mongoTemplate.count(query, DeviceCheckin.class);
		List<DeviceCheckin> result=mongoTemplate.find(query.with(pageable), DeviceCheckin.class);
		Page<DeviceCheckin> page=new PageImpl<DeviceCheckin>(result, pageable, cnt);
		return page;
	}
	
	/* (non-Javadoc)
	 * @see com.foreveross.bsl.push.repository.custom.DeviceCheckinRepositoryCustom#existsByTags(java.util.Map, java.lang.String)
	 */
	@Override
	public boolean existsByTags(Map<String, String> tags, String appId) {
		Query query=this.buildQuery(tags, appId);
		query.skip(0).limit(1);
		List<DeviceCheckin> list=this.mongoTemplate.find(query, DeviceCheckin.class);
		return list!=null && !list.isEmpty();
	}
	
	private Query buildQuery(Map<String, String> tags, String appId){
		List<Criteria> cris=new ArrayList<Criteria>();
		for(Map.Entry<String, String> entry : tags.entrySet()){
			String key=entry.getKey(), value=entry.getValue();
			String[] values=StringUtils.split(value, ",");
			List<Criteria> subcs=new ArrayList<Criteria>();
			for(String v : values){
				subcs.add(Criteria.where("k").is(key).and("v").is(v));
			}
			Criteria orGroup=new Criteria();
			orGroup.orOperator(subcs.toArray(new Criteria[0]));
			cris.add(Criteria.where("tags").elemMatch(orGroup));
		}
		Criteria cri=new Criteria();
		cri.andOperator(cris.toArray(new Criteria[0])).and("appId").is(appId);
		Query query=Query.query(cri);
		return query;
	}
	
	@Override
	public int clearToken(String token) {
		Query query = Query.query(Criteria.where("token").in(token));
		Update update = Update.update("token", null);
		WriteResult wr=this.mongoTemplate.updateMulti(query, update, DeviceCheckin.class);
		return wr.getN();
	}

}
